#include "soapH.h"
#include "Service.nsmap"
#include <iostream>
#include <fstream>
#include <conio.h>

using namespace std;

//const char server[] = "localhost:5555";


void menu(){
	system("cls");
	printf("\n");
	printf("\nUsage: (write): 1  | 1 help\n");
	printf("\nUsage: (getProperties): 2 <id_item_1> ... <id_item_n> | 2 help\n");
	printf("\nUsage: (subscription): 3 <id_item_1> ... <id_item_n> | 3 help\n");		
	printf("\nUsage: (subscriptionCancel): 4 <serverSubHandle> [ClientRequestHandle] | 4 help\n");
	printf("\nUsage: (read): 5  | 5 help\n");		
	printf("\nUsage: (getStatus): 6  | 6 help\n");
	printf("\nUsage: (browse): 7 | 7 help  \n");
	//printf("\nUsage: (Config): 8 <ip>:<puerto> \n");
	printf("\nUsage: (SubscriptionPolledRefresh): 9 <serverSubHandle_1> ... <serverSubHandle_n>  | 9 help\n");	
}

void help(int op){
	system("cls");
	printf("\n");
	switch(op){
		case 1:
			printf("This service writes the value for one or more items.");
			break;
		case 10:
			printf("If set to FALSE, then the server will return only the changed Items between this SubscriptionPolledRefresh request and the previous request.If TRUE the server will return all Items specified by the original Subscribe.");
			break;
		case 2:
			printf("Get the properties of the item IDs");
			break;
		case 3:
			printf("The client initiates the subscription and the server returns a subscription handle in response to the request.");
			break;
		case 31:
			printf("The SubscriptionPingRate is the requested rate in milliseconds that the server should reevaluate the existence of the client.");
			printf("If the client has not had any communication in the specified period, then the Server is free to clean up all resources associated with that client for this Subscription.");
			printf("If the SubscriptionPingRate is 0, then the server will use its own algorithm to reevaluate the existence of the client.");
			break;
		case 32:
			printf("If TRUE the server will return item values which are readily available for inclusion in the SubscribeResponse. Depending on when the SubscriptionPolledRefresh is requested, these items may or may not be updated in the first SubscriptionPolledRefresh.");
			break;
		case 33:
			printf("The client specifies the rate in milliseconds at which the server should check for value changes. If no item-specific sampling rate is specified, sampling will be based on the rate of the item list.");
			break;
		case 4:
			printf("The server will cancel a subscription (ServerSubHandle) and allow the server to clean up any resources associated with the subscription.");
			break;
		case 5:
			printf("This service provides the ability to read the value and quality for one or more items.");
			break;
		case 6:
			printf("The purpose of the GetStatus service is:"); 
			printf("\n		1. It provides a mechanism for checking the status of the server."); 
			printf("\n		2. It provides a common mechanism for obtaining vendor-specific information about the server"); 
			printf("\n		3. Provides insight for clients as to the relative time synchronization");
		case 7:
			printf("This service provides the items in the server");
			break;
		case 9:
			printf("This service refreshes the data items from the last SubscriptionPolledRefresh.");
			break;

		default:
			break;								
	 }
	printf("\n");

}

int main(int argc, char **argv)
{ 	
	  char server[100];	  
	  memset(server,0,sizeof(server));
	  ifstream fi ("data.cfg");
	  fi>>server;	
	 
	  fi.close();
	  if(strlen(server)==0){
		  cout<<"<ip>:<port> = ";
		  cin>>server;		  
		  ofstream fo("data.cfg");
		  fo<<server;
		  fo.close();
	  }   	 
	
	  if (argc < 2)
	  { 
		menu();
		exit(0);		
	  }
	 
	 switch (*argv[1])
	  { 
		case '1': 	
			if(argc == 3) 
				{
					help(1);
					exit(0);
				}
			break;
		case '2':   
			if(argc<3){
					menu();
					exit(0);
				}
			if(argc == 3 && strcmp(argv[2],"help")==0)
			{
				help(2);
				exit(0);
			}
			break;			
		case '3':
			 if(argc<3){
				menu();
				exit(0);
			 }
			 if(argc==3 && strcmp(argv[2], "help")==0)
			 {
				 help(3);
				 exit(0);
			 }
			break;
		case '4':
			if(argc < 3){
					menu();
					exit(0);
				}
			if(argc==3 && strcmp(argv[2],"help")==0)
			{
				help(4);
				exit(0);
			}
			break;
		case '5':
			if(argc == 3){				
				help(5);
				exit(0);
			}			
			break;
		case '6':
			if(argc==3)
				if (strcmp(argv[2],"help")==0){
					help(6);
					exit(0);
				}
			break;
		case '7':
			if(argc==3)
				if(strcmp(argv[2],"help")==0){
					help(7);
					exit(0);
				}
			break;
		case '8':
			if(argc<3){
				menu();
				exit(0);
			}			
			break;		
		case '9':
			if(argc < 3){
				menu();
				exit(0);
			}
			if(argc==3 && strcmp(argv[2],"help")==0)
			{
				help(9);
				exit(0);
			}
			break;
		case '10':
			break;
		default:
			menu();
			exit(0);					
	 }


  struct soap soap; 
  bool result = false;

  //write
  _ns1__WriteResponse wr; 
  _ns1__Write ns;

  //read
  _ns1__Read rs;
  _ns1__ReadResponse rr;

  //browse
  _ns1__Browse b;
  _ns1__BrowseResponse br;

  //getStatus
  _ns1__GetStatus gs;
  _ns1__GetStatusResponse sr; 

  //getProperties 
  _ns1__GetProperties gp;
  _ns1__GetPropertiesResponse gr;


  //subscribe	
  _ns1__Subscribe s;
  _ns1__SubscribeResponse ssr;

  //subscribeCancel
  _ns1__SubscriptionCancel sc;
  _ns1__SubscriptionCancelResponse scr;

  //SubscriptionPolledRefresh
  _ns1__SubscriptionPolledRefresh spr;
  _ns1__SubscriptionPolledRefreshResponse sprr;

  //Config
  //_ns1__Config c;
  //_ns1__ConfigResponse cc;


  //SubscriptionPolledRefresh
  if(*argv[1]=='10'){	 	 
	  char op[10];
	  memset(op,0,sizeof(op));
	  cout<<endl<<"ReturnAllItems (y,n)? h(help)"<<endl;
	  cin>>op;
	  while(op[0]=='h')
	  {
		  help(10);
		  cout<<endl<<"ReturnAllItems (y,n)? h(help)"<<endl;
		  cin>>op;
	  }

	  if(op[0]=='y')
		  spr.ReturnAllItems = true;
	  else
		  spr.ReturnAllItems = false;


	  for(int i=2; i<argc; i++)
	  {	
		  char *serverSubHandle = argv[i];
		  string *serverSubHandleS = new string(serverSubHandle);
		  spr.ServerSubHandles.push_back(*serverSubHandleS);

	  }
  }   

  /*if(*argv[1]=='8'){	  	  
	  char * dir_ip = argv[2];
	  string *new_dir_ip = new string(dir_ip);
	  c.dir_ip = *new_dir_ip;
	  server = argv[2];
  }*/

  if(*argv[1]=='1'){
	  ns.ItemList = new ns1__WriteRequestItemList();
	  char c[100];
	  do{
		  ns1__ItemValue *itemValue = new ns1__ItemValue();
		  char name[100];
		  char value[100];
		  memset(name, 0, sizeof(name));
		  memset(value,0,sizeof(value));
		  cout<<endl<<"Name item: ";
		  cin.getline(name,100);
		  string *itenName = new string(name);
		  itemValue->ItemName = itenName;
		  cout<<endl<<"value: ";
		  cin.getline(value,100);
		  string *val = new string(value);
		  itemValue->Value = (char *)val->c_str();		  
		  ns.ItemList->Items.push_back(itemValue);		  
		  memset(c,0,sizeof(c));
		  cout<<endl<<"another item (s,n)?";		  
		  cin.getline(c,100);
	  }while(c[0]=='s');
  }
   if(*argv[1]=='4'){
	  char *ServerSubHandle = argv[2];	    
	  string * ServerSubHandleS = new string(ServerSubHandle);	   
	  sc.ServerSubHandle = ServerSubHandleS;	  
	  cout<<"ServerSubHandle = "<<*(sc.ServerSubHandle)<<endl;
	  if(argc > 3){
		  char *ClientRequestHandle = argv[3];
		  string *ClientRequestHandleS = new string(ClientRequestHandle);
		  sc.ClientRequestHandle = ClientRequestHandleS;
		  cout<<"ClientRequestHandle = "<<*(sc.ClientRequestHandle)<<endl;
	  }
   }  
   if(*argv[1]=='3'){//subscription

	  char aux[100];
	  memset(aux,0,sizeof(aux));
	  cout<<endl<<"Subscription ping rate:  h(help)";
	  cin>>aux;
	  while(strcmp(aux,"h")==0){
		  help(31);
		  memset(aux,0,sizeof(aux));
		  cout<<endl<<"Subscription ping rate:  h(help)";
		  cin>>aux;
	  }
	  

	  s.SubscriptionPingRate = atoi(aux);
	  //cout<<s.SubscriptionPingRate;
	  //s.SubscriptionPingRate = 20000;	
	  memset(aux,0,sizeof(aux));	
	  cout<<endl<<"Return values on reply: ? h(help)";
	  cin>>aux;
	  while(strcmp(aux,"h")==0){
		  help(32);
		  memset(aux,0,sizeof(aux));
		  cout<<endl<<"Return values on reply: (y,n)? h(help)";
		  cin>>aux;
	  }

	  if(strcmp(aux,"y")==0)
		s.ReturnValuesOnReply = true;
	  else
		s.ReturnValuesOnReply = false;

	  s.ItemList = new ns1__SubscribeRequestItemList();

	  memset(aux,0,sizeof(aux));
	  cout<<endl<<"Requested sampling rate(list): h(help)";
	  cin>>aux;
	  while(strcmp(aux,"h")==0){
		  help(33);
		  memset(aux,0,sizeof(aux));
		  cout<<endl<<"Requested sampling rate(list): h(help)";
		  cin>>aux;
	  }


	  int requestedSamplingRate;
	  requestedSamplingRate = atoi(aux);	  
	  s.ItemList->RequestedSamplingRate = new int(requestedSamplingRate);	  
	   for(int i=2; i<argc; i++)
		{		
			ns1__SubscribeRequestItem *subscribeRequesItem = new ns1__SubscribeRequestItem();
			subscribeRequesItem->ItemName = new string(argv[i]);			
			
			//cout<<endl<<"RequestedSamplingRate(item) :";
			//cin>>requestedSamplingRate;

			subscribeRequesItem->RequestedSamplingRate = new int(requestedSamplingRate);
			s.ItemList->Items.push_back(subscribeRequesItem);			
		}

	   for(int i=0; i<s.ItemList->Items.size(); i++)
		   cout<<endl<<"items: = "<<*(s.ItemList->Items[i]->ItemName)<<endl;  


  }
  if(*argv[1]=='2'){//getProperties		  

	  for(int i=2; i<argc; i++)
	  {			
		  ns1__ItemIdentifier *itemIdentifier = new ns1__ItemIdentifier(); 		  
		  itemIdentifier->ItemName = new string(argv[i]);
		  gp.ItemIDs.push_back(itemIdentifier);		
	  }
  }

  for(int i=0; i<gp.ItemIDs.size(); i++){
	  cout<<"itemID = "<<*(gp.ItemIDs[i]->ItemName)<<endl;
  }
  if(*argv[1]== '5'){//read
	  rs.ItemList = new ns1__ReadRequestItemList();
	  char c[100];
	  do{
		  ns1__ReadRequestItem *item = new ns1__ReadRequestItem();
		  char name[100];		  
		  memset(name,0,sizeof(name));
		  cout<<endl<<"Nombre item: ";
		  cin.getline(name,100);
		  item->ItemName = new string(name);
		  rs.ItemList->Items.push_back(item);
		  cout<<endl<<"another item (s,n)?";
		  //cin>>c;
		  cin.getline(c,100);
	  }while(c[0]=='s');
  }
  soap_init(&soap);

  switch (*argv[1])
  { 
	case '1': 		
		//soap_call___ns1__Write(&soap, server, "",&ns,&wr);
		soap_call___ns1__Write(&soap, server, "",&ns,&wr);
		result = true;
		break;
	case '2': 		
		soap_call___ns1__GetProperties(&soap,server,"",&gp,&gr);
		result = true;			
		break; 
	case '3':	
		soap_call___ns1__Subscribe(&soap,server,"",&s,&ssr);
		result = true;		
		break;	
	case '4':
		soap_call___ns1__SubscriptionCancel(&soap,server,"",&sc,&scr);
		result = true;
		break;
	case '5':    
		soap_call___ns1__Read(&soap,server,"",&rs,&rr);
		result = true;
		break;
	case '6':
		soap_call___ns1__GetStatus(&soap,server,"",&gs,&sr);
		result = true;
		break;
	case '7': 
		soap_call___ns1__Browse(&soap,server,"",&b,&br);
		result = true;
		break; 
	/*case '8':
		soap_call___ns1__Config(&soap, server, "", &c,&cc);
		result = true;
		break;*/
	case '9':	
		
		while (!_kbhit()) {
			Sleep(15000);
			soap_call___ns1__SubscriptionPolledRefresh(&soap,server,"",&spr,&sprr);

			cout<<"Subscribe Response"<<endl;
			
				for(int i=0; i<sprr.RItemList[0]->Items.size(); i++)
				{
					cout<<"Nombre item = " <<*(sprr.RItemList[0]->Items[i]->ItemName)<<endl;
					cout<<"Valor actual = "<<sprr.RItemList[0]->Items[i]->Value<<endl;										
				}	
				cout<<"(press any key to exit)"<<endl;
		}
		
		result = true;
		break;
    default:
		fprintf(stderr, "Unknown command\n");
		exit(0);
  }
	

  if (soap.error)
  { 
	  soap_print_fault(&soap, stderr);
	  exit(1);
  }
  else{
		  
	  if(result==true){		  

		  switch (*argv[1])
		  { 
			case '3':								
				cout<<"ServerSubHandle : = "<<*(ssr.ServerSubHandle)<<endl;
				break;
			case '4': 
				if(argc > 3) //ClientRequestHandle specified
					cout<<"ClientRequestHandle: = "<<*(scr.ClientRequestHandle)<<endl;				
				break;
			case '5': 		
				if(rr.RItemList->Items.size()==0)
					cout<<"the item doesn't exist"<<endl;
				else{
					for(int i=0; i<rr.RItemList->Items.size(); i++)
						cout<<endl<<"Item: "<<*(rr.RItemList->Items[i]->ItemName)<<" "<<rr.RItemList->Items[i]->Value;

				}											
				break;	 
			case '6': 	
				
				cout<<"product version: "<<*(sr.Status->ProductVersion)<<endl;	
				cout<<"SupportedInterface: "<<sr.Status->SupportedInterfaceVersions[0]<<endl;
				cout<<"StartTime: "<<sr.Status->StartTime<<endl;
				break;			
			case '2':
				
				for(int i=0; i<gr.PropertyLists.size(); i++)
				{
					for(int j=0; j<gr.PropertyLists[i]->Properties.size(); j++){
						cout<<"ItemName: = "<<gr.PropertyLists[i]->Properties[j]->Name<<endl;
						cout<<"ItemValue: = "<<gr.PropertyLists[i]->Properties[j]->Value<<endl;
					}
				}	
				break;
			case '7':
				cout<<"Browsing..."<<endl;
				if(br.Elements.size() == 0)
					cout<<"No items"<<endl;
				else{
				for(int i=0; i<br.Elements.size(); i++)
					cout<< *(br.Elements[i]->ItemName)<<endl;
				}
				break;
			/*case '8':
				cout<<"dir ip: = "<<cc.dir_ip;
				break;*/
			case '9':
				cout<<"Subscribe Response"<<endl;
				for(int i=0; i<sprr.RItemList[0]->Items.size(); i++)
				{
					cout<<"Nombre item = " <<*(sprr.RItemList[0]->Items[i]->ItemName)<<endl;
					cout<<"Valor actual = "<<sprr.RItemList[0]->Items[i]->Value<<endl;
				}



		  }				
	  }
  }

  
  soap_destroy(&soap);
  soap_end(&soap);
  soap_done(&soap);
  return 0;
}